package com.gopay.bis.service.bank.impl;

import com.gopay.bis.common.util.BisPayCheckUtils;
import com.gopay.bis.common.util.TransUtil;
import com.gopay.bis.manager.bank.BankOrderManager;
import com.gopay.bis.manager.bank.CustCorpInfoManager;
import com.gopay.bis.manager.bank.NuccSerialManager;
import com.gopay.bis.manager.bank.expay.NuccExPayManager;
import com.gopay.bis.manager.bank.external.BisPayMessageManager;
import com.gopay.bis.manager.bank.payconfig.BisBankExtConfigManager;
import com.gopay.bis.manager.bank.payconfig.BisBankProductLimitMerchantsManager;
import com.gopay.bis.manager.bank.payconfig.BisBankSpecialMerchantsManager;
import com.gopay.bis.service.bank.BankOrderService;
import com.gopay.bis.service.bank.external.BisExternalPlatformService;
import com.gopay.bis.service.bank.query.BisBankWhiteListMerchantsService;
import com.gopay.common.Result;
import com.gopay.common.cache.client.RedisClient;
import com.gopay.common.cipher.utils.LoggerMaskUtils;
import com.gopay.common.constants.bank.BankConstants;
import com.gopay.common.constants.bank.BankOrderStatus;
import com.gopay.common.constants.bank.BankOrderType;
import com.gopay.common.constants.bank.BisBankBusinessProd;
import com.gopay.common.constants.bank.BisBankInterfaceChannel;
import com.gopay.common.constants.bank.BisMerProductLimit;
import com.gopay.common.constants.bank.NuccConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.constants.txncd.IntTxnCd;
import com.gopay.common.cps.manager.order.CpsGeneralMainOrderQueryManager;
import com.gopay.common.domain.bank.BankOrder;
import com.gopay.common.domain.bank.BaseMessage;
import com.gopay.common.domain.bank.ExPayBaseMessage;
import com.gopay.common.domain.bank.abc.ebank.AbcB2bMessage;
import com.gopay.common.domain.bank.abc.ebank.AbcB2cMessage;
import com.gopay.common.domain.bank.bobj.ebank.BobjB2cMessage;
import com.gopay.common.domain.bank.bocom.ebank.pay.b2b.req.BocomB2bReq;
import com.gopay.common.domain.bank.citic.ebank.pay.CiticB2bMessage;
import com.gopay.common.domain.bank.citic.ebank.pay.CiticB2cMessage;
import com.gopay.common.domain.bank.cmbc.ebank.CmbcB2bMessage;
import com.gopay.common.domain.bank.cmbc.ebank.CmbcB2cMessage;
import com.gopay.common.domain.bank.external.BisBankMerchant;
import com.gopay.common.domain.bank.external.BisPayMessage;
import com.gopay.common.domain.bank.hxbc.ebank.pay.req.HXEB2CReqPay;
import com.gopay.common.domain.bank.icbc.ebank.pay.IcbcB2cMessage;
import com.gopay.common.domain.bank.khpay.ebank.KhPayMessage;
import com.gopay.common.domain.bank.nucc.ebank.pay.res.NuccEbankRes;
import com.gopay.common.domain.bank.yspay.ebank.YspayMessage;
import com.gopay.common.domain.bis.BaseBisBankExtConfig;
import com.gopay.common.domain.cps.CpsGenMainOrder;
import com.gopay.common.domain.cust.CustCorpInfo;
import com.gopay.common.domain.user.mcc.UserMccTransformReq;
import com.gopay.common.domain.user.mcc.UserMccTransformRes;
import com.gopay.common.exception.GopayException;
import com.gopay.common.order.bankorder.trade.InitialSpringBeanName;
import com.gopay.common.order.bankorder.trade.TradeType;
import com.gopay.common.user.mcc.manager.UserMccTransformManager;
import com.gopay.common.util.DateUtils;
import com.gopay.common.util.spring.SpringContextUtil;
import com.gopay.remote.bank.BankInteractRemoteService;
import com.gopay.remote.bank.ExPayInteractRemoteService;
import com.gopay.remote.bank.MicroPayInteractRemoteService;
import com.gopay.remote.bank.ScanPayInteractRemoteService;
import com.gopay.remote.bank.WcPayInteractRemoteService;
import java.math.BigDecimal;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.StaleObjectStateException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

/**
 * @BankInteractServiceImpl.java
 * @author WangHongFei
 */
@Service("bankInteractService")
public class BankInteractServiceImpl implements BankInteractRemoteService {

	private static Logger logger = LoggerFactory.getLogger(BankInteractServiceImpl.class);
	private static final String AUTO_ROUTING = "on"; // 银行自动路由开关
	@Resource(name = "bankOrderService")
	private BankOrderService bankOrderService;
    @Resource(name = "bisExternalPlatformService")
    private BisExternalPlatformService bisExternalPlatformService;
    @Resource(name = "cpsGeneralMainOrderQueryManager")
    private CpsGeneralMainOrderQueryManager mainOrderQuery;
    @Resource(name = "bankOrderManager")
    private BankOrderManager bankOrderManager;
    @Resource(name = "bisBankExtConfigManager")
    BisBankExtConfigManager bisBankExtConfigManager;    
    @Resource(name = "bisPayMessageManager")
    BisPayMessageManager bisPayMessageManager;
    @Resource(name = "bisBankSpecialMerchantsManager")
    BisBankSpecialMerchantsManager bisBankSpecialMerchantsManager;
//    @Resource(name = "bisBankSmallMerchantsManager")
//    BisBankSmallMerchantsManager bisBankSmallMerchantsManager;
    @Resource(name = "userMccTransformManager")
    private UserMccTransformManager userMccTransformManager;
    @Resource(name = "custCorpInfoManager")
    CustCorpInfoManager custCorpInfoManager;
	@Resource(name = "scanPayInteractService")
	private ScanPayInteractRemoteService scanPayInteractService;
	@Resource(name = "wcPayInteractService")
	private WcPayInteractRemoteService wcPayInteractService;
	@Resource(name = "microPayInteractService")
	private MicroPayInteractRemoteService microPayInteractService;
	@Resource(name = "bisConfig")
    private Map<String, String> bisConfig;
	@Resource(name = "bisBankWhiteListMerchantsService")
    private BisBankWhiteListMerchantsService bisBankWhiteListMerchantsService;
	@Resource(name = "bisBankProductLimitMerchantsManager")
    BisBankProductLimitMerchantsManager bisBankProductLimitMerchantsManager;
	@Resource(name = "exPaybankInteractService")
    private ExPayInteractRemoteService exPaybankInteractService;
    @Resource(name = "nuccSerialManager")
	private NuccSerialManager nuccSerialManager;
	
	@Value("${NUCC.SERIAL.CONTROL}")
    private String nuccSerialControl;
	
	@Override
	public Result pay(BaseMessage base) {
		/**央行检测 要求身份照掩码处理 sj 2017-11-03*/
		logger.error("BankInteractServiceImpl银行支付处理base对象："+LoggerMaskUtils.maskString(ToStringBuilder.reflectionToString(base)));
		Result result = new Result();
		try {
			// 获取订单信息与银行信息
			CpsGenMainOrder mainOrder = getMainOrder(base.getOrderId());
			
			
			// 获取SPRING加载的BeanName
			String beanName = getBeanName(mainOrder, base.getBankIntrChann(),base.getBankBusProd());
			base.setBankOrderId(base.getOrderId());
			
			
			BankInteractRemoteService bankService = (BankInteractRemoteService) SpringContextUtil.getBean(beanName);
			
			if(bisBankProductLimitMerchantsManager.isExistEnableMerchants(mainOrder.getMainRecvCustId(), base.getBank(), base.getBankBusProd().value, BisMerProductLimit.SMALL.value)){
                base.setSmallMer(true);
            }
           
//            if (bisBankSmallMerchantsManager.isEnableBankSmallMerchant(mainOrder.getMainRecvCustId(), base.getBank())) {
//                base.setSmallMer(true);
//            }
            
            //2017-04-26新增大额商户判断
//            if(bisBankProductLimitMerchantsManager.isExistEnableMerchants(mainOrder.getMainRecvCustId(), base.getBank(), base.getBankBusProd().value, BisMerProductLimit.BIG.value)){
//                base.setBigMer(true);
//            }
            
            boolean supportCredit = true;
            // 判断充值交易类型
            if (IntTxnCd._00500.value.equals(mainOrder.getGopayIntTxnCd())) {
                if (mainOrder.getRelevanceGopayOrderId() != null) {
                    // 登录支付订单
                    if (bisBankSpecialMerchantsManager.isEnableBankSpecialMerchant(mainOrder.getMainRecvCustId(),
                            base.getBank())) {
                        supportCredit = false;
                    }
                } else {
                    // 普通充值订单
                    supportCredit = false;
                }
            } else {
                // 普通支付订单
                if (bisBankSpecialMerchantsManager.isEnableBankSpecialMerchant(mainOrder.getMainRecvCustId(),
                        base.getBank())) {
                    supportCredit = false;
                }
            }
            base.setSupportCredit(supportCredit);
            
			if(!BisPayCheckUtils.checkExternalOrderID(base.getOrderId())){
				logger.info("-----一银行产品码------"+base.getBankBusProd()+"-------银行码------"+base.getBank());
				
				BaseBisBankExtConfig bankConfig = new BaseBisBankExtConfig();
                if (isRouteOrWhiteList(base.getSpecial2())) {
	                // 增加银行自动路由开关 add by zhengxue
	                bankConfig = bisBankExtConfigManager.findExtConfigByBankChannelAndBankBusProd(base.getBankBusProd(), base.getBankIntrChann(), base.getBank());
                } else {
	                bankConfig = bisBankExtConfigManager.findExtConfigByBankCodeAndBankBusProd(base.getBankBusProd(), base.getBank());
	                
	                /**  
	                 * 特殊处理  5001商户强制走渠道
	                 * 
	                 * */
	                if(base.getBank().equals(BankConstants.BANK_LOGO_ABC)&& BisBankBusinessProd._00.value.equals(base.getBankBusProd().value)){
	                    UserMccTransformReq userM = new UserMccTransformReq();
	                    userM.setBankCode(BankConstants.BANK_LOGO_ABC);
	                    userM.setCustId(base.getSpecial2());
	                    UserMccTransformRes userRes = userMccTransformManager.graspUserMccInfo(userM);
	                    if(userRes!= null && userRes.getGopayMccCode() != null && BankConstants.GOPAY_MCC_CODE.equals(userRes.getGopayMccCode())){
	                        bankConfig = bisBankExtConfigManager.findExtConfigByBankChannelAndBankBusProd(base.getBankBusProd(), BisBankInterfaceChannel._13, base.getBank());
	                    }
	                }

//              if (base.getBank().equals(BankConstants.BANK_LOGO_BOC) && BisBankBusinessProd._00.value.equals(base.getBankBusProd().value)){
//                  CustCorpInfo custInfo = custCorpInfoManager.get(base.getSpecial2());
//                  if(custInfo!= null && BankConstants.GOPAY_MCC_CODE.equals(custInfo.getGopayMccCode())){
//                      bankConfig = bisBankExtConfigManager.findExtConfigByBankChannelAndBankBusProd(base.getBankBusProd(), base.getBankIntrChann(), base.getBank());
//                  }
//              }
                    if (base.getBank().equals(BankConstants.BANK_LOGO_BOC) && BisBankBusinessProd._00.value.equals(base.getBankBusProd().value)){
                        CustCorpInfo custInfo = custCorpInfoManager.get(base.getSpecial2());
                        if(custInfo!= null && ("9999").equals(custInfo.getGopayMccCode())){
                            bankConfig = bisBankExtConfigManager.findExtConfigByBankChannelAndBankBusProd(base.getBankBusProd(), BisBankInterfaceChannel._13, base.getBank());
                        }
                    }
           
                    if(base.getBank().equals(BankConstants.BANK_LOGO_CMBC) && BisBankBusinessProd._00.value.equals(base.getBankBusProd().value)){
                        UserMccTransformReq userM = new UserMccTransformReq();
                        userM.setBankCode(BankConstants.BANK_LOGO_CMBC);
                        userM.setCustId(base.getSpecial2());
                        UserMccTransformRes userRes = userMccTransformManager.graspUserMccInfo(userM);
                        if(userRes!= null && userRes.getGopayMccCode() != null && ("9999").equals(userRes.getGopayMccCode())){
                            bankConfig = bisBankExtConfigManager.findExtConfigByBankChannelAndBankBusProd(base.getBankBusProd(), BisBankInterfaceChannel._13  , base.getBank());
                        }
                    }
                
                    if(base.getBank().equals(BankConstants.BANK_LOGO_BOCOM) && BisBankBusinessProd._00.value.equals(base.getBankBusProd().value)){
                        UserMccTransformReq userM = new UserMccTransformReq();
                        userM.setBankCode(BankConstants.BANK_LOGO_BOCOM);
                        userM.setCustId(base.getSpecial2());
                        UserMccTransformRes userRes = userMccTransformManager.graspUserMccInfo(userM);
                        if(userRes!= null && userRes.getGopayMccCode() != null && ("9999").equals(userRes.getGopayMccCode())){
                            bankConfig = bisBankExtConfigManager.findExtConfigByBankChannelAndBankBusProd(base.getBankBusProd(), BisBankInterfaceChannel._13  , base.getBank());
                        }
                    }
                }
                logger.error("gobankcontroller route end: "
                        + new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date()));
				
				//设置一级私钥路径
				base.setPrivateKeyPath(bankConfig.getIntrMerPravkeyPath());
				//设置一级私钥密码
				base.setPrivatePwd(bankConfig.getIntrMerPravkeyPwd());
				//设置二级私钥路径
				base.setPrivateKeyPath2nd(bankConfig.getIntrMer2ndPravkeyPath());
				//设置二级私钥密码
				base.setPrivatePwd2nd(bankConfig.getIntrMer2ndPravkeyPwd());
				//设置公钥路径
				base.setPublicKeyPath(bankConfig.getIntrBankPubkeyPath());
				//设置商户号
				base.setMerID(bankConfig.getIntrMernum1());
				//设置二级商户号
				base.setMerID2nd(bankConfig.getIntrMernum2());			
				//设置结算账户网点联行号
				base.setBranchCode(bankConfig.getBranchCode());
				//设置银行支付地址
				base.setPayUrl(bankConfig.getPayUrl());			
				//设置支付后台通知地址
				base.setPayRuturnUrl(bankConfig.getPayRuturnUrl());
				//设置支付后前通知地址
				base.setPayNotifyUrl(bankConfig.getPayNotifyUrl());	
			}
			
			result = bankService.pay(base);
			base = (BaseMessage)result.getDefaultModel();
			/**央行检测 要求身份照掩码处理 sj 2017-11-03*/
			logger.error("BankInteractServiceImpl银行支付签名返回处理base对象：" +
					LoggerMaskUtils.maskString(ToStringBuilder.reflectionToString(base)));
			// 校验银行订单不能为多条
            List<BankOrder> bankOrders =  bankOrderService.getBankOrdersByGopayOrderId(base.getOrderId());
            if(bankOrders!=null && bankOrders.size()>0){
                result.setResultCode(ProcCodeConstants.PROC_CODE_100E5015);// 已存在相同的订单
                result.setSuccess(false);
                return result;
            }
            // 新增bankOrder info
            base.setBankOrderType(BankOrderType.GOPAY_BIS_ORDER);//订单类型：新平台订单
            bankOrderService.addBankOrder(base);
            // 新增上送银行订单客户信息
            if(base.getSendBankCustId()!=null && !"".equals(base.getSendBankCustId())){
                 bankOrderService.addSendBankOrder(base);
            }
            
        } catch (GopayException e) {
            logger.error("BankInteractServiceImpl pay error: ", e);
            result.setResultCode(e.getErrCode());
            result.setSuccess(false);
        } catch (Exception e) {
            logger.error("BankInteractServiceImpl pay error: ", e);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100F1002);
            result.setSuccess(false);
        }
        return result;
    }

	@Override
	public Result bankBack(BaseMessage base) {
		/**央行检测 要求身份照掩码处理 sj 2017-11-03*/
		logger.error("BankInteractServiceIfmpl银行返回处理base对象：" + 
				LoggerMaskUtils.maskString(ToStringBuilder.reflectionToString(base)));
		Result result = new Result();
		try {		
			if (base.getBankOrderId() == null || base.getBankOrderId().equals("")) {
			    BankOrder bankOrder = new BankOrder();
			    base.setOutStlmCd(base.getBank());
			    BaseBisBankExtConfig bankConfig = new BaseBisBankExtConfig();
                // 银行自动路由修改支付返回无订单号订单,获取产品渠道方法(由获取当前生效渠道改为根据银行、产品、渠道码获取) add by zhengxue
                bankConfig = bisBankExtConfigManager.findExtConfigByBankChannelAndBankBusProd(base.getBankBusProd(), base.getBankIntrChann(), base.getBank());
                
				if(bankConfig!=null){
                    //设置一级私钥路径
                    base.setPrivateKeyPath(bankConfig.getIntrMerPravkeyPath());
                    //设置一级私钥密码
                    base.setPrivatePwd(bankConfig.getIntrMerPravkeyPwd());
                    //设置二级私钥路径
                    base.setPrivateKeyPath2nd(bankConfig.getIntrMer2ndPravkeyPath());
                    //设置二级私钥密码
                    base.setPrivatePwd2nd(bankConfig.getIntrMer2ndPravkeyPwd());
                    //设置公钥路径
                    base.setPublicKeyPath(bankConfig.getIntrBankPubkeyPath());              
                }
                
                // 验签
                String beanName = getBankBeanName(base); //只返回密文银行获取beanName
                BankInteractRemoteService bankService = (BankInteractRemoteService) SpringContextUtil.getBean(beanName);
                result = bankService.bankBack(base);
                base = (BaseMessage) result.get("res");
                /**央行检测 要求身份照掩码处理 sj 2017-11-03*/
                logger.error("BankInteractServiceImpl验签返回处理base对象：" + 
                		LoggerMaskUtils.maskString(ToStringBuilder.reflectionToString(base)));
                if (result.isSuccess()&& (Boolean) result.getDefaultModel()) {
                    //记录前台通知时间
                    if(base.isFront()){
                        bankOrderManager.updateFrontBackTime(base.getOrderId());
                        logger.info("记录前台返回时间：订单号【"+base.getOrderId()+"】记录成功，bis_bank_main_order表更新前台返回时间");
                        return result;
                    }
                    // 验签成功
                    if(result.isOrderStatus()){
                        bankOrder = bankOrderManager.getBankOrderById(base.getBankOrderId());
                        Map<String, String> param = (Map<String, String>) result.getModel("isNotifyCashier");
                        String amt = (String) param.get("amt"); // 银行返回交易金额
                        if (bankOrder.getSendBankAmt() != null
                                && bankOrder.getSendBankAmt().compareTo(new BigDecimal(amt)) != 0) {
                            // 银行返回金额与平台上送金额不符
                            bankOrderManager.updateAmountError(bankOrder.getOrderId());
                            logger.error("银行【 "+beanName+"】返回处理结果：国付宝订单号【"+base.getOrderId()+"】金额比对异常");
                            result.setSuccess(false);
                            result.setResultCode(ProcCodeConstants.PROC_CODE_100E5079);
                            result.setErrorMsg("通知订单金额不一致");
                            return result;
                        }
                        
                        if (base.getBankIntrChann() != null && BisBankInterfaceChannel._18.value.equals(base.getBankIntrChann().value)) {
							//处理网联逻辑
                        	bankOrderManager.updateBackSuccess(base.getOrderId(), base.getSpecial4());
						} else {
							//原有逻辑
							bankOrderManager.updateBackSuccess(base.getOrderId());
						}
	                    logger.error("银行【 "+beanName+"】返回处理结果：订单号【"+base.getOrderId()+"】验签成功，bis_bank_main_order表更新成功状态");
	                }else{
	                    logger.error("银行【 "+beanName+"】返回处理结果：订单号【"+base.getOrderId()+"】验签成功，订单未成功");
	                }
				} else {
					// 验签失败
					bankOrderManager.updateBackVerifyFail(base.getOrderId());
					logger.error("银行【 "+beanName+"】返回处理结果：订单号【"+base.getOrderId()+"】验签失败，bis_bank_main_order表更新失败状态");
				}
				
				base.setOrderId(bankOrder.getOrderId());
				// 是否验签成功过
				if (StringUtils.equals(bankOrder.getOrderStatus(),BankOrderStatus.BANK_CALL_SUCCESS)) {
					result.setDefaultModel(true);
					result.setSuccess(true);
				}
				return result;
			}
			BankOrder bankOrder = null;
			bankOrder = bankOrderManager.getBankOrderById(base.getBankOrderId());
			// 自动路由需使用主订单表对象,挪到此处获取 add by zhengxue
            CpsGenMainOrder mainOrder = new CpsGenMainOrder();
			
        	String bankBizProdCode = bankOrder.getBankBizProdCode();
        	base.setOrderId(bankOrder.getOrderId());
        	if(BisBankBusinessProd._00.value.equals(bankBizProdCode)){
        		base.setBankBusProd(BisBankBusinessProd._00);
        	}else if(BisBankBusinessProd._01.value.equals(bankBizProdCode)){
        		base.setBankBusProd(BisBankBusinessProd._01);
			}else if(BisBankBusinessProd._11.value.equals(bankBizProdCode)){
				base.setBankBusProd(BisBankBusinessProd._11);
        	}else{
            	throw new GopayException(ProcCodeConstants.PROC_CODE_100E1141);
            }

        	//如果为外部平台订单
			if(BisPayCheckUtils.checkExternalOrderID(bankOrder.getOrderId())){
				//获取外部订单交易对象
				BisPayMessage bisPayMessage = bisPayMessageManager.getBisPayMessageByGopayOrderId(bankOrder.getOrderId());
				//如果使用外部平台自己的订单
				if(bisPayMessage.getIsThroughBis().equals("1")){
					base.setOutStlmCd(base.getBank());
					BisBankMerchant bisBankMerchant = bisExternalPlatformService.getBankMerchant(bisPayMessage.getPlatformId(), bankOrder.getBankCode(), base.getBankBusProd().value);
					//设置一级私钥路劲
					base.setPrivateKeyPath(bisBankMerchant.getIntrMerPravkeyPath());
					 //设置一级私钥密码
					base.setPrivatePwd(bisBankMerchant.getIntrMerPravkeyPwd());
					//设置二级私钥路径
					base.setPrivateKeyPath2nd(bisBankMerchant.getIntrMer2ndPravkeyPath());
					//设置二级私钥密码
					base.setPrivatePwd2nd(bisBankMerchant.getIntrMer2ndPravkeyPwd());             
					//设置公钥路径
					base.setPublicKeyPath(bisBankMerchant.getIntrBankPubkeyPath());	
				}else{
					base.setOutStlmCd(base.getBank());
					BaseBisBankExtConfig bankConfig = bisBankExtConfigManager.findExtConfigByBankCodeAndBankBusProd(base.getBankBusProd(), bankOrder.getBankCode());
					//设置一级私钥路径
					base.setPrivateKeyPath(bankConfig.getIntrMerPravkeyPath());
					//设置一级私钥密码
					base.setPrivatePwd(bankConfig.getIntrMerPravkeyPwd());
					//设置二级私钥路径
					base.setPrivateKeyPath2nd(bankConfig.getIntrMer2ndPravkeyPath());
					//设置二级私钥密码
					base.setPrivatePwd2nd(bankConfig.getIntrMer2ndPravkeyPwd());
					//设置公钥路径
					base.setPublicKeyPath(bankConfig.getIntrBankPubkeyPath());
				}
			}else{
			    // 获取订单信息与银行信息
                mainOrder = getMainOrder(bankOrder.getOrderId());
				base.setOutStlmCd(base.getBank());
				BaseBisBankExtConfig bankConfig = new BaseBisBankExtConfig();
				if (isRouteOrWhiteList(mainOrder.getMerId())) {
                    // 增加银行自动路由开关 add by zhengxue
                    bankConfig = bisBankExtConfigManager.findExtConfigByBankChannelAndBankBusProd(base.getBankBusProd(), BisBankInterfaceChannel.get(bankOrder.getInterfaceChennelCode()), bankOrder.getBankCode());
                } else {
                    bankConfig = bisBankExtConfigManager.findExtConfigByBankCodeAndBankBusProd(base.getBankBusProd(), bankOrder.getBankCode());
                }
				
				//设置一级私钥路径
				base.setPrivateKeyPath(bankConfig.getIntrMerPravkeyPath());
				//设置一级私钥密码
				base.setPrivatePwd(bankConfig.getIntrMerPravkeyPwd());
				//设置二级私钥路径
				base.setPrivateKeyPath2nd(bankConfig.getIntrMer2ndPravkeyPath());
				//设置二级私钥密码
				base.setPrivatePwd2nd(bankConfig.getIntrMer2ndPravkeyPwd());
				//设置公钥路径
				base.setPublicKeyPath(bankConfig.getIntrBankPubkeyPath());
			}
			String beanName = "";
			//如果定单为外部平台
			if(BisPayCheckUtils.checkExternalOrderID(bankOrder.getOrderId())){
				beanName = getExternalBeanName(base,bankOrder);
			}else{
				// 获取订单信息与银行信息
				mainOrder = getMainOrder(bankOrder.getOrderId());
				// 获取SPRING加载的BeanName
				beanName = getBeanName(mainOrder,BisBankInterfaceChannel.get(bankOrder.getInterfaceChennelCode()),BisBankBusinessProd.get(bankOrder.getBankBizProdCode()));
			}
			/****************** 处理银行多次通知 begin ***********************/
			// 是否验签成功过
			if (StringUtils.equals(bankOrder.getOrderStatus(),BankOrderStatus.BANK_CALL_SUCCESS)) {
				BankInteractRemoteService bankService = (BankInteractRemoteService) SpringContextUtil.getBean(beanName);
				result = bankService.bankBack(base);
				result.setDefaultModel(true);
				result.setSuccess(true);
				if (base.isFront()) {
					//记录前台通知时间
					bankOrderManager.updateFrontBackTime(base.getOrderId());
					logger.info("多次通知记录前台返回时间：订单号【"+base.getOrderId()+"】记录成功，bis_bank_main_order表更新前台返回时间");
				}
				return result;
			}
			// 是否验签失败过
			if (StringUtils.equals(bankOrder.getOrderStatus(),BankOrderStatus.VERIFY_FAIL)) {
				result.setDefaultModel(false);
				result.setSuccess(true);
				return result;
			}
			/************** 处理银行多次通知 end *******************/
			// 验签
			BankInteractRemoteService bankService = (BankInteractRemoteService) SpringContextUtil.getBean(beanName);
			result = bankService.bankBack(base);				
			if (base.isFront()) {
				// 前台通知不更新银行流水状态，直接返回
				if (result.isSuccess() && (Boolean) result.getDefaultModel()){
					//记录前台通知时间
					bankOrderManager.updateFrontBackTime(base.getOrderId());
					logger.info("记录前台返回时间：订单号【"+base.getOrderId()+"】记录成功，bis_bank_main_order表更新前台返回时间");
				}
				return result;
			}
			if (result.isSuccess() && (Boolean) result.getDefaultModel()) {
				// 验签成功
				if(result.isOrderStatus()){
				    Map<String, String> param = (Map<String, String>) result.getModel("isNotifyCashier");
                    String amt = (String) param.get("amt"); // 银行返回交易金额
                    if (bankOrder.getSendBankAmt() != null
                            && bankOrder.getSendBankAmt().compareTo(new BigDecimal(amt)) != 0) {
                        // 银行返回金额与平台上送金额不符
                        bankOrderManager.updateAmountError(bankOrder.getOrderId());
                        logger.error("银行【 "+beanName+"】返回处理结果：国付宝订单号【"+base.getOrderId()+"】金额比对异常");
                        result.setSuccess(false);
                        result.setResultCode(ProcCodeConstants.PROC_CODE_100E5079);
                        result.setErrorMsg("通知订单金额不一致");
                        return result;
                    }
                    
					bankOrderManager.updateBackSuccess(bankOrder.getOrderId());
					logger.error("银行【 "+beanName+"】返回处理结果：国付宝订单号【"+base.getOrderId()+"】验签成功，bis_bank_main_order表更新成功状态");
				}else{
					logger.error("银行【 "+beanName+"】返回处理结果：国付宝订单号【"+base.getOrderId()+"】验签成功，订单未成功");
				}
			} else {
				// 验签失败
				bankOrderManager.updateBackVerifyFail(bankOrder.getOrderId());
				logger.error("银行【 "+beanName+"】返回处理结果：国付宝订单号【"+base.getOrderId()+"】验签失败，bis_bank_main_order表更新失败状态");
			}
		} catch (GopayException e) {
			logger.error("BankInteractServiceImpl bankBack error: ", e);
			result.setResultCode(e.getErrCode());
			result.setSuccess(false);
		} catch (Exception e) {
			logger.error("BankInteractServiceImpl bankBack error: ", e);
			result.setResultCode(ProcCodeConstants.PROC_CODE_100F1002);
			result.setSuccess(false);
		}
		return result;
	}
	
	@Override
	public Result query(BaseMessage base) {	
		Result result = new Result();
		try {
		    if (base.getBankOrderId() == null || base.getBankOrderId().equals("")) {
		        // 北京银行查询返回验签单独处理
	            base.setOutStlmCd(base.getBank());
	            BaseBisBankExtConfig bankConfig = new BaseBisBankExtConfig();
                // 银行自动路由修改北京银行查询获取产品渠道方法(由获取当前生效渠道改为根据银行、产品、渠道码获取) add by zhengxue
                bankConfig = bisBankExtConfigManager.findExtConfigByBankChannelAndBankBusProd(base.getBankBusProd(), base.getBankIntrChann(), base.getBank());
	            
	            //设置一级私钥路径
	            base.setPrivateKeyPath(bankConfig.getIntrMerPravkeyPath());
	            //设置一级私钥密码
	            base.setPrivatePwd(bankConfig.getIntrMerPravkeyPwd());
	            //设置二级私钥路径
	            base.setPrivateKeyPath2nd(bankConfig.getIntrMer2ndPravkeyPath());
	            //设置二级私钥密码
	            base.setPrivatePwd2nd(bankConfig.getIntrMer2ndPravkeyPwd());
	            //设置公钥路径
	            base.setPublicKeyPath(bankConfig.getIntrBankPubkeyPath());      
	            // 验签
	            String beanName = getBankBeanName(base);
	            BankInteractRemoteService bankService = (BankInteractRemoteService) SpringContextUtil.getBean(beanName);
	            result = bankService.bankBack(base);
	            base = (BaseMessage) result.get("res");
	            /**央行检测 要求身份照掩码处理 sj 2017-11-03*/
	            logger.error("BankInteractServiceImpl北京银行B2C查询验签返回处理base对象：" +
	            		LoggerMaskUtils.maskString(ToStringBuilder.reflectionToString(base)));
	            return result;
	        }
		    
			base.setSupportCredit(true);
			/**央行检测 要求身份照掩码处理 sj 2017-11-03*/
			logger.error("BankInteractServiceImpl银行查询处理base对象：" +
					LoggerMaskUtils.maskString(ToStringBuilder.reflectionToString(base)));
			CpsGenMainOrder mainOrder = getMainOrder(base.getOrderId());
			// 获取SPRING加载的BeanName
			String outStlmId = getOutStlmId(mainOrder,base.getBankIntrChann(),base.getBankBusProd());
			base.setOutStlmCd(outStlmId);
			base.setAmount(mainOrder.getTotalOrderAmt());
			if (mainOrder.getSettleAmt() != null) {
	            // 发送银行金额取结算金额,若为空则取总金额字段
	            base.setAmount(mainOrder.getSettleAmt());
	        }
			String beanName = getBeanName(mainOrder,base.getBankIntrChann(),base.getBankBusProd());
			BankInteractRemoteService bankService = (BankInteractRemoteService) SpringContextUtil.getBean(beanName);	
			//银行订单
            List<BankOrder> bankOrders = bankOrderService.getBankOrdersByGopayOrderId(base.getOrderId());
            String disableCreditCard = ((BankOrder) bankOrders.get(0)).getDisableCreditCard();
            String disableSmallMerchant = ((BankOrder) bankOrders.get(0)).getDisableSmallMerchant();
            String specialbigMerchant = ((BankOrder) bankOrders.get(0)).getSpecialBigMerchant();
            if ("1".equals(disableCreditCard)) {
                base.setSupportCredit(false);
            }
            
            if("1".equals(disableSmallMerchant)){
                base.setSmallMer(true);
            }
            if("1".equals(specialbigMerchant)){
                base.setBigMer(true);
            }
            
            if(!BisPayCheckUtils.checkExternalOrderID(base.getOrderId())){
                // 根据银行业务产品代码、通道代码、银行代码获取通道配置信息
                BaseBisBankExtConfig bankConfig = bisBankExtConfigManager.findExtConfigByBankChannelAndBankBusProd(base.getBankBusProd(), base.getBankIntrChann(), base.getBank());
                //设置一级私钥路径
                base.setPrivateKeyPath(bankConfig.getIntrMerPravkeyPath());
                //设置一级私钥密码
                base.setPrivatePwd(bankConfig.getIntrMerPravkeyPwd());
                //设置二级私钥路径
                base.setPrivateKeyPath2nd(bankConfig.getIntrMer2ndPravkeyPath());
                //设置二级私钥密码
                base.setPrivatePwd2nd(bankConfig.getIntrMer2ndPravkeyPwd());
                //设置公钥路径
                base.setPublicKeyPath(bankConfig.getIntrBankPubkeyPath());
                //设置商户号
                base.setMerID(bankConfig.getIntrMernum1());
                //设置二级商户号
                base.setMerID2nd(bankConfig.getIntrMernum2());
                //设置结算账户网点联行号
                base.setBranchCode(bankConfig.getBranchCode());
                //设置银行查询地址
                base.setQueryUrl(bankConfig.getQueryUrl()); 
            }
            //查询
            result = bankService.query(base);
            /**央行检测 要求身份照掩码处理 sj 2017-11-03*/
            logger.error("BankInteractServiceImpl银行查询返回base对象："+
            		LoggerMaskUtils.maskString(ToStringBuilder.reflectionToString(result)));
        } catch (GopayException e) {
            logger.error("BankInteractServiceImpl query error: ", e);
            result.setResultCode(e.getErrCode());
            result.setSuccess(false);
        } catch (Exception e) {
            logger.error("BankInteractServiceImpl query error: ", e);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100F1002);
            result.setSuccess(false);
        }
        return result;
    }
    
    @Override
    public Result queryBack(BaseMessage base) {
        return null;
    }



    @Override
    public Result refund(BaseMessage base) {
    	/**央行检测 要求身份照掩码处理 sj 2017-11-03*/
        logger.error("BankInteractServiceImpl银行退款处理base对象："+
        		LoggerMaskUtils.maskString(ToStringBuilder.reflectionToString(base)));
        Result result = new Result();
        try {
            // 获取原支付订单信息与银行信息
            CpsGenMainOrder mainOrder = getMainOrder(base.getTkOriOrderId());
            // 获取原支付银行订单
            List<BankOrder> bankOrders = bankOrderService.getBankOrdersByGopayOrderId(base.getTkOriOrderId());
            BankOrder bankOrder = bankOrders.get(0);
            logger.error("退款发起  bankorder------"+ToStringBuilder.reflectionToString(bankOrder));
            if (!isSendTkOrder(bankOrder.getOutOrderId())) {
                // 已存在处理中退款交易
                result.setResultCode(ProcCodeConstants.PROC_CODE_100E6089);
                result.setSuccess(false);
                logger.error("watch--after isSendTkOrder--"+bankOrder.getOrderId());
                return result;
            }
            String gopayOrderId = base.getOrderId();
            BisBankInterfaceChannel channel = BisBankInterfaceChannel.get(bankOrder.getInterfaceChennelCode());
            BisBankBusinessProd prod = BisBankBusinessProd.get(bankOrder.getBankBizProdCode());
            
            // 获取SPRING加载的BeanName
            String outStlmId = getOutStlmId(mainOrder, channel, prod);
            base.setOutStlmCd(outStlmId);
            BaseBisBankExtConfig bankConfig = new BaseBisBankExtConfig();
            // 根据银行业务产品代码、通道代码、银行代码获取通道配置信息
            bankConfig = bisBankExtConfigManager.findExtConfigByBankChannelAndBankBusProd(prod, channel,
                    bankOrder.getBankCode());
            // 退款银行订单号
            if (channel.value.equals(BisBankInterfaceChannel._13.value)) {
            	if(BisBankBusinessProd._05.value.equals(prod.value)
            			|| BisBankBusinessProd._15.value.equals(prod.value)){
            		//民生i支付快捷渠道
        			base.setBankOrderId("TK" + TransUtil.processOrderIdTo14Digit(base.getOrderId()));
        		}else{
        			// 民生i支付渠道
                    base.setBankOrderId("IP" + TransUtil.processOrderIdTo14Digit(base.getOrderId()));
        		}
                
            } else if (channel.value.equals(BisBankInterfaceChannel._15.value)) {
                // 微信扫码中信银行渠道
                base.setBankOrderId("WF" + TransUtil.processOrderIdTo14Digit(base.getOrderId()));
            } else if (channel.value.equals(BisBankInterfaceChannel._17.value)) {
                // 微信/支付宝民生银行渠道
                base.setBankOrderId("MS" + TransUtil.processOrderIdTo14Digit(base.getOrderId()));
            } else if (channel.value.equals(BisBankInterfaceChannel._16.value)) {
                // 微信/兴业银行渠道
                base.setBankOrderId("XY" + TransUtil.processOrderIdTo14Digit(base.getOrderId()));
            } else if (channel.value.equals(BisBankInterfaceChannel._20.value)) {
                // 平安跨行支付渠道(商户号+8位日期YYYYMMDD+8位流水)
                base.setBankOrderId(bankConfig.getIntrMernum1() + DateUtils.getCurrDate().substring(0, 8)
                        + base.getOrderId().substring(8));
            } else if (channel.value.equals(BisBankInterfaceChannel._25.value)) {
                // 微信/兴业银行渠道
                base.setBankOrderId("PA" + TransUtil.processOrderIdTo14Digit(base.getOrderId()));
            }else if(channel.value.equals(BisBankInterfaceChannel._18.value)){
                 //如果缓存中没有流水号规则缓存则主动调用接口
                if(!RedisClient.exists(NuccConstants.NUCC_SERIAL_REDIS_KEY)){
                	nuccSerialManager.getFlowIdRule();                    
                }
                //主动调用接口后还是没有则报错
                if (!RedisClient.exists(NuccConstants.NUCC_SERIAL_REDIS_KEY)) {
                    //抛出缓存中不存在流水号异常
                    throw new GopayException(ProcCodeConstants.PROC_CODE_100E6121);
                }
                //从缓存中获取规则组装流水号
                Map<String, String> map = RedisClient.hgetAll(NuccConstants.NUCC_SERIAL_REDIS_KEY);
                String serial = map.get(NuccConstants.NUCC_SERIAL_REDIS_FIELD + new SecureRandom().nextInt(map.size()));
                //交易流水号
                base.setBankOrderId(DateUtils.format(new Date(), "yyyyMMdd")+base.getOrderId()+nuccSerialControl+serial);
            }else if (channel.value.equals(BisBankInterfaceChannel._28.value)) {
                // 微信/兴业银行渠道
                base.setBankOrderId("SP" + TransUtil.processOrderIdTo14Digit(base.getOrderId()));
            }else {
                base.setBankOrderId(base.getOrderId());
            }
         
            //logger.error("-------refund bankOrderId-------"+channel);
           
            base.setTkOriBankOrderId(bankOrder.getOutOrderId());
            base.setBankBusProd(BisBankBusinessProd._12); // 退款
            base.setBankIntrChann(channel);
            base.setBank(bankOrder.getBankCode());
            base.setBankOrderType(BankOrderType.GOPAY_BIS_ORDER);// 订单类型：新平台订单
            
            logger.error("before add refund outOrderId: " + base.getBankOrderId()
                    + ", orderId: " + gopayOrderId);
            
            // 保存退款订单
            bankOrderService.addBankOrder(base);
            
            result.setSuccess(true);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100S1000);
            logger.error("after add refund outOrderId: " + base.getBankOrderId()
                    + ", orderId: " + gopayOrderId);
        } catch (GopayException e) {
            logger.error("BankInteractServiceImpl refund error: ", e);
            result.setResultCode(e.getErrCode());
            result.setSuccess(false);
        } catch (Exception e) {
            logger.error("BankInteractServiceImpl refund error: ", e);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100F1002);
            result.setSuccess(false);
        }
        return result;
    }
    
    @Override
	public Result sendBankRefund(BaseMessage base) {
    	/**央行检测 要求身份照掩码处理 sj 2017-11-03*/
    	 logger.error("BankInteractServiceImpl银行退款发往银行处理base对象："+
    			 LoggerMaskUtils.maskString(ToStringBuilder.reflectionToString(base)));
         Result result = new Result();
         try {
        	 String gopayOrderId = base.getOrderId();
        	  BankOrder refundBankOrder = bankOrderService
                      .getBankOrderById(base.getBankOrderId());
           
             // 获取原支付银行订单
        	  BankOrder bankOrder = bankOrderService .getBankOrderById(base.getTkOriBankOrderId());
        	  base.setTkOriOrderId(bankOrder.getOrderId());
             // 获取原支付订单信息与银行信息
             CpsGenMainOrder mainOrder = getMainOrder(bankOrder.getOrderId());
             logger.error("发往银行退款发起  mainOrder------"+ToStringBuilder.reflectionToString(mainOrder));
             Result statusResult = getOrderStatus(bankOrder);
             logger.error(gopayOrderId + "send bank procCode: "
                     + toLogString(statusResult));
             // 发送银行前加orderStatus判断，已受理状态才发送
             
             if (!BankOrderStatus.ACCEPTED.equals(refundBankOrder.getOrderStatus())) {
                 logger.error(gopayOrderId + "send bank orderstatus: "
                         + toLogString(statusResult));
                 result.setResultCode(ProcCodeConstants.PROC_CODE_100E6066);
                 result.setSuccess(false);
                 return result;
             }
             logger.error("发往银行退款发起  bankorder------"+ToStringBuilder.reflectionToString(refundBankOrder));
             if (!isSendTkOrder(bankOrder.getOutOrderId())) {
                 // 已存在处理中退款交易
                 result.setResultCode(ProcCodeConstants.PROC_CODE_100E6089);
                 result.setSuccess(false);
                 return result;
             }
           
             BisBankInterfaceChannel channel = BisBankInterfaceChannel.get(bankOrder.getInterfaceChennelCode());
             BisBankBusinessProd prod = BisBankBusinessProd.get(bankOrder.getBankBizProdCode());
             
             /**
              * 判断走的是那个退款渠道,微信扫码或者微信APP
              */
             if(prod.value.equals(BisBankBusinessProd._16.value)||prod.value.equals(BisBankBusinessProd._17.value)){
             	result=scanPayInteractService.refund(base);
            	if (null == result) {
                    logger.error("send bank result is null, outOrderId："
                            + refundBankOrder.getOutOrderId());
                    throw new GopayException(ProcCodeConstants.PROC_CODE_100E6066);// 状态处理中
                }
                //更新退款订单状态
                bankResUpdateOrder(result, refundBankOrder);
             	return result;
             
             }
             /**
              * 微信公众号
              */
             if(prod.value.equals(BisBankBusinessProd._18.value)){
             	result=wcPayInteractService.refund(base);
            	if (null == result) {
                    logger.error("send bank result is null, outOrderId："
                            + refundBankOrder.getOutOrderId());
                    throw new GopayException(ProcCodeConstants.PROC_CODE_100E6066);// 状态处理中
                }
                //更新退款订单状态
                bankResUpdateOrder(result, refundBankOrder);
             	return result;
             }
             
             /**
              * 快捷支付
              */
             if(prod.value.equals(BisBankBusinessProd._15.value)
             		|| prod.value.equals(BisBankBusinessProd._05.value)){
             	ExPayBaseMessage exBase = new ExPayBaseMessage();
             	exBase.setAmount(new BigDecimal(0.00));
             	BeanUtils.copyProperties(exBase, base);
             	
             	result=exPaybankInteractService.refund(exBase);
             	
             	return result;
             }
             /**
              * 小额免密支付
              */
             if(prod.value.equals(BisBankBusinessProd._25.value)){
                 result=microPayInteractService.refund(base);
                 if (null == result) {
                     logger.error("send bank result is null, outOrderId："
                             + refundBankOrder.getOutOrderId());
                     throw new GopayException(ProcCodeConstants.PROC_CODE_100E6066);// 状态处理中
                 }
                 //更新退款订单状态
                 bankResUpdateOrder(result, refundBankOrder);
                 return result;
              }
             
             // 获取SPRING加载的BeanName
             String outStlmId = getOutStlmId(mainOrder, channel, prod);
             base.setOutStlmCd(outStlmId);
             BaseBisBankExtConfig bankConfig = new BaseBisBankExtConfig();
             // 根据银行业务产品代码、通道代码、银行代码获取通道配置信息
             bankConfig = bisBankExtConfigManager.findExtConfigByBankChannelAndBankBusProd(prod, channel,
                     bankOrder.getBankCode());
             if(bankConfig!=null){
                 base.setMerID(bankConfig.getIntrMernum1());
             }
             
             String beanName = getBeanName(mainOrder, channel, prod);
             BankInteractRemoteService bankService = (BankInteractRemoteService) SpringContextUtil.getBean(beanName);
             base.setTkOriBankOrderId(bankOrder.getOutOrderId());
             base.setBankBusProd(BisBankBusinessProd._12); // 退款
             base.setBankIntrChann(channel);
             base.setBank(bankOrder.getBankCode());
             base.setBankOrderType(BankOrderType.GOPAY_BIS_ORDER);// 订单类型：新平台订单
             // 退款
             result = bankService.refund(base);
             if (null == result) {
                 logger.error("send bank result is null, outOrderId："
                         + refundBankOrder.getOutOrderId());
                 throw new GopayException(ProcCodeConstants.PROC_CODE_100E6066);// 状态处理中
             }
             //更新退款订单状态
             bankResUpdateOrder(result, refundBankOrder);
             logger.error("BankInteractServiceImpl银行退款返回base对象：" + ToStringBuilder.reflectionToString(result));
         } catch (GopayException e) {
             logger.error("BankInteractServiceImpl refund error: ", e);
             if (null == result) {
             	result = new Result();
			 }
             result.setResultCode(e.getErrCode());
             result.setSuccess(false);
         } catch (Exception e) {
             logger.error("BankInteractServiceImpl refund error: ", e);
             result.setResultCode(ProcCodeConstants.PROC_CODE_100F1002);
             result.setSuccess(false);
         }
         return result;
	}
    
   /**
    * 获取退款订单当前状态
    * @param bankOrder
    * @return
    */
    private Result getOrderStatus(BankOrder bankOrder) {
        Result r = new Result();
        r.setSuccess(true);
        if (null == bankOrder) {
            r.setResultCode(ProcCodeConstants.PROC_CODE_100E6001);
            return r;// 不存在记录
        }
        if (BankOrderStatus.PROCESS.equals(bankOrder.getOrderStatus())) {
            r.setResultCode(ProcCodeConstants.PROC_CODE_100E6066);
            r.setDefaultModel(bankOrder);
            return r;// 处理中
        }
        if (BankOrderStatus.BANK_CALL_SUCCESS
                .equals(bankOrder.getOrderStatus())
                || BankOrderStatus.AUTO_CHECK_SUCCESS.equals(bankOrder
                        .getOrderStatus())
                || BankOrderStatus.CHECK_SUCCESS.equals(bankOrder
                        .getOrderStatus())) {
            r.setResultCode(ProcCodeConstants.PROC_CODE_100S1000);
            r.setDefaultModel(bankOrder);
            return r;// 成功
        }
        r.setResultCode(ProcCodeConstants.PROC_CODE_100E5019);
        return r;// 失败
    }

    /**
     * 日志输出类型转换
     * 
     * @param log
     * @return String
     */
    private String toLogString(Object log) {
        return ToStringBuilder.reflectionToString(log,
                ToStringStyle.DEFAULT_STYLE);
    }

    
    /**
     * 银行相应更新退款订单
     * 
     * @param result
     * @param bankOrder
     */
    private void bankResUpdateOrder(Result result, BankOrder bankOrder) {
        bankOrder = bankOrderService.getBankOrderById(bankOrder.getOutOrderId());
        // 银行订单状态
        String   status = BankOrderStatus.PROCESS;// 进行中状态，等待银行异步通知
        
        bankOrder.setOrderStatus(status);
        bankOrder.setSendBankTm(new Date());
        bankOrder.setLastUpdTs(new Date());
        try {
            bankOrderService.updateBankOrder(bankOrder);
        } catch (StaleObjectStateException e) {
            Date finishTime = bankOrder.getTranFinishTime();
            bankOrder = bankOrderService.getBankOrderById(bankOrder.getOutOrderId());
            bankOrder.setOrderStatus(status);
            bankOrder.setLastUpdTs(new Date());
            if (finishTime != null) {
                bankOrder.setTranFinishTime(finishTime);
            }
            bankOrderService.updateBankOrder(bankOrder);
        }
    }
    

    @Override
    public Result refundBack(BaseMessage base) {
    	/**央行检测 要求身份照掩码处理 sj 2017-11-03*/
        logger.error("BankInteractServiceImpl银行退款返回处理base对象：" + 
        		LoggerMaskUtils.maskString(ToStringBuilder.reflectionToString(base)));
        Result result = new Result();
        try {
            BankOrder bankOrder = new BankOrder();
            BankOrder oriBankOrder = new BankOrder();
            // 获取退款订单
            bankOrder = bankOrderManager.getBankOrderById(base.getBankOrderId());
            // 原支付订单
            oriBankOrder = bankOrderManager.getBankOrderById(bankOrder.getOriOutOrderId());
            base.setOrderId(bankOrder.getOrderId());

            String beanName = "";
            CpsGenMainOrder mainOrder = new CpsGenMainOrder();
            // 获取订单信息与银行信息
            mainOrder = getMainOrder(oriBankOrder.getOrderId());
            // 获取SPRING加载的BeanName
            beanName = getBeanName(mainOrder, BisBankInterfaceChannel.get(oriBankOrder.getInterfaceChennelCode()),
                    BisBankBusinessProd.get(oriBankOrder.getBankBizProdCode()));

            /****************** 处理银行多次通知 begin ***********************/
            // 是否验签成功过
            if (StringUtils.equals(bankOrder.getOrderStatus(), BankOrderStatus.BANK_CALL_SUCCESS)) {
                BankInteractRemoteService bankService = (BankInteractRemoteService) SpringContextUtil.getBean(beanName);
                result = bankService.refundBack(base);
                result.setDefaultModel(true);
                result.setSuccess(true);
                return result;
            }
            // 是否验签失败过
            if (StringUtils.equals(bankOrder.getOrderStatus(), BankOrderStatus.VERIFY_FAIL)) {
                result.setDefaultModel(false);
                result.setSuccess(true);
                return result;
            }
            /************** 处理银行多次通知 end *******************/
            // 退款返回验签
            BankInteractRemoteService bankService = (BankInteractRemoteService) SpringContextUtil.getBean(beanName);
            result = bankService.refundBack(base);

            if (result.isSuccess() && (Boolean) result.getDefaultModel()) {
                Map<String, String> param = (Map<String, String>) result.getModel("isNotifyCashier");
                // 验签成功
                if (result.isOrderStatus()) {
                    String amt = (String) param.get("amt"); // 银行返回退款金额
                    if (bankOrder.getSendBankAmt() != null
                            && bankOrder.getSendBankAmt().compareTo(new BigDecimal(amt)) != 0) {
                        // 退款银行返回金额与平台上送金额不符
                        bankOrderManager.updateAmountError(bankOrder.getOrderId());
                        logger.error("退款银行【 " + beanName + "】返回处理结果：国付宝订单号【" + base.getOrderId() + "】金额比对异常");
                        result.setSuccess(false);
                        result.setResultCode(ProcCodeConstants.PROC_CODE_100E5079);
                        result.setErrorMsg("退款通知订单金额不一致");
                        return result;
                    }

                    bankOrderManager.updateBackSuccess(bankOrder.getOrderId());
                    logger.error("退款银行【 " + beanName + "】返回处理结果：国付宝订单号【" + base.getOrderId()
                            + "】验签成功，bis_bank_main_order表更新成功状态");
                } else {
                    // 退款失败更新失败原因
                    bankOrder.setRemark2((String) param.get("retMsg"));
                    bankOrderManager.updateBankOrder(bankOrder);
                    logger.error("退款银行【 " + beanName + "】返回处理结果：国付宝订单号【" + base.getOrderId() + "】验签成功，订单未成功");
                }
            } else {
                // 验签失败
                bankOrderManager.updateBackVerifyFail(bankOrder.getOrderId());
                logger.error("退款银行【 " + beanName + "】退款返回处理结果：国付宝订单号【" + base.getOrderId()
                        + "】验签失败，bis_bank_main_order表更新失败状态");
            }
        } catch (GopayException e) {
            logger.error("BankInteractServiceImpl refundBack error: ", e);
            result.setResultCode(e.getErrCode());
            result.setSuccess(false);
        } catch (Exception e) {
            logger.error("BankInteractServiceImpl refundBack error: ", e);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100F1002);
            result.setSuccess(false);
        }
        return result;
    }   

    @Override
    public Result refundQuery(BaseMessage base) {   
        Result result = new Result();
        try {
        	/**央行检测 要求身份照掩码处理 sj 2017-11-03*/
            logger.error("BankInteractServiceImpl退款查询处理base对象：" + 
            		LoggerMaskUtils.maskString(ToStringBuilder.reflectionToString(base)));
            // 获取原支付银行订单
            BankOrder bankOrder = bankOrderService.getBankOrderById(base.getTkOriBankOrderId());
            // 获取原支付订单
            CpsGenMainOrder mainOrder = getMainOrder(bankOrder.getOrderId());
            BisBankInterfaceChannel channel = BisBankInterfaceChannel.get(bankOrder.getInterfaceChennelCode());
            BisBankBusinessProd prod = BisBankBusinessProd.get(bankOrder.getBankBizProdCode());
            // 获取SPRING加载的BeanName
            String outStlmId = getOutStlmId(mainOrder, channel, prod);
            base.setOutStlmCd(outStlmId);
            base.setAmount(mainOrder.getTotalOrderAmt());
            String beanName = getBeanName(mainOrder, channel, prod);
            BankInteractRemoteService bankService = (BankInteractRemoteService) SpringContextUtil.getBean(beanName);

            if (!BisPayCheckUtils.checkExternalOrderID(base.getOrderId())) {
                // 根据银行业务产品代码、通道代码、银行代码获取通道配置信息
                BaseBisBankExtConfig bankConfig = bisBankExtConfigManager.findExtConfigByBankChannelAndBankBusProd(
                        prod, channel, base.getBank());
                // 设置一级私钥路径
                base.setPrivateKeyPath(bankConfig.getIntrMerPravkeyPath());
                // 设置一级私钥密码
                base.setPrivatePwd(bankConfig.getIntrMerPravkeyPwd());
                // 设置二级私钥路径
                base.setPrivateKeyPath2nd(bankConfig.getIntrMer2ndPravkeyPath());
                // 设置二级私钥密码
                base.setPrivatePwd2nd(bankConfig.getIntrMer2ndPravkeyPwd());
                // 设置公钥路径
                base.setPublicKeyPath(bankConfig.getIntrBankPubkeyPath());
                // 设置商户号
                base.setMerID(bankConfig.getIntrMernum1());
                // 设置二级商户号
                base.setMerID2nd(bankConfig.getIntrMernum2());
                // 设置结算账户网点联行号
                base.setBranchCode(bankConfig.getBranchCode());
                // 设置银行查询地址
                base.setQueryUrl(bankConfig.getQueryUrl());
            }
            // 查询
            result = bankService.refundQuery(base);
            logger.error("BankInteractServiceImpl退款查询返回base对象：" + ToStringBuilder.reflectionToString(result));
        } catch (GopayException e) {
            logger.error("BankInteractServiceImpl refundQuery error: ", e);
            result.setResultCode(e.getErrCode());
            result.setSuccess(false);
        } catch (Exception e) {
            logger.error("BankInteractServiceImpl refundQuery error: ", e);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100F1002);
            result.setSuccess(false);
        }
        return result;
    }
    
    /**
     * @author guomuye
     * 闇�涓�釜filedate
     */
    @Override
    public Result dayend(BaseMessage base) {
    	/**央行检测 要求身份照掩码处理 sj 2017-11-03*/
        logger.error("BankInteractServiceImpl银行查询处理base对象："+
        		LoggerMaskUtils.maskString(ToStringBuilder.reflectionToString(base)));
        Result result = new Result();
        try {
            // 鑾峰彇SPRING鍔犺浇鐨凚eanName
            String beanName = getBeanName(base);
            if(!SpringContextUtil.containsBean(beanName)){
                logger.error("spring bean does not exist: " + base.getBank()+"-"+base);
                result.setResultCode(ProcCodeConstants.PROC_CODE_300G1011);
                result.setErrorMsg(beanName+":spring获得bankServiceImpl调用类失败");
                return result;
            }
            BankInteractRemoteService bankService = (BankInteractRemoteService) SpringContextUtil.getBean(beanName);
            result = bankService.dayend(base);
            logger.info("BankInteractServiceImpl银行查询返回base对象："+ToStringBuilder.reflectionToString(result));
        } catch (GopayException e) {
            logger.error("BankInteractServiceImpl dayend error: ", e);
            result.setResultCode(e.getErrCode());
            result.setSuccess(false);
        } catch (Exception e) {
            logger.error("BankInteractServiceImpl dayend error: ", e);
            result.setResultCode(ProcCodeConstants.PROC_CODE_300G1000);
            result.setSuccess(false);
        }
        return result;
    }

    /**
     * 获取订单信息
     * @param orderId
     * @return CpsGenMainOrder
     * @throws GopayException
     */
    private CpsGenMainOrder getMainOrder(String orderId) throws GopayException {
        if (orderId == null || "".equals(orderId)) {
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E5041);
        }
        // 获取主订单表
        CpsGenMainOrder mainOrder = mainOrderQuery.get(orderId);
        if (mainOrder == null) {
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E5041);
        }
        return mainOrder;
    }

    /**
     * 获取SPRING加载的BeanName
     * @author guomuye
     * @throws GopayException
     */
    private String getBeanName(BaseMessage base)throws GopayException {
        int tradeType = base.getTradeType();
        String buffix = TradeType.getTradeType(tradeType);
        String suffix = base.getBank();
        return suffix+"-"+buffix;
    }
    /**
     * 获取SPRING加载的BeanName
     * 
     * <pre>
     * BeanName规范:银行编码-交易类型，如TBANK-B2B
     * </pre>
     * 
     * @param mainOrder
     *            订单信息
     * @param inChann
     *            银行信息
     * @return
     * @throws GopayException
     */
    private String getBeanName(CpsGenMainOrder mainOrder,BisBankInterfaceChannel inChann, BisBankBusinessProd bankBusProd)throws GopayException {
        String beanSuffix = TradeType.getOrderTrandType(mainOrder.getPayChannel());
        String outStlmId = getOutStlmId(mainOrder,inChann,bankBusProd);
        String beanName = outStlmId + "-" + beanSuffix;
        return beanName;
    }

    /**
     * 获取SPRING加载的BeanName
     * BeanName规范:银行编码-交易类型，如TBANK-B2B
     * @param message 璁㈠崟淇℃伅
     * @param bankOrder 閾惰淇℃伅
     * @return String
     * @throws GopayException
     */
    private String getExternalBeanName(BaseMessage message,BankOrder bankOrder) throws GopayException {
        String beanName ="";
        if (bankOrder != null) {
            String beanSuffix="";
            String outStlmId="";
            String chennelCodeValue = BisBankInterfaceChannel.get(bankOrder.getInterfaceChennelCode()).value;
            String bankBizProdCode = BisBankBusinessProd.get(bankOrder.getBankBizProdCode()).value;         
            if(BisBankBusinessProd._00.value.equals(bankBizProdCode)){
                beanSuffix = "B2C";
            }else if(BisBankBusinessProd._01.value.equals(bankBizProdCode)){
                beanSuffix = "B2B";
            }else if(BisBankBusinessProd._11.value.equals(bankBizProdCode)){
                beanSuffix = "B2C";
            }else{
                throw new GopayException(ProcCodeConstants.PROC_CODE_100E1141);
            }
            if (StringUtils.equals(TradeType.TRADE_TYPE_B2C, beanSuffix)) {
                outStlmId = InitialSpringBeanName.getOutStlmCd(chennelCodeValue,bankBizProdCode,bankOrder.getBankCode());
            } else {
                outStlmId = bankOrder.getBankCode();
            }
            message.setBank(outStlmId);
            beanName = outStlmId+"-"+beanSuffix;
            return beanName;
        }else{
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E1141);
        }
    }
    
    /**
     * 获取SPRING加载的BeanName(银行返回密文)
     * BeanName规范:银行编码-交易类型，如TBANK-B2B
     * @param base
     * @return String
     * @throws GopayException
     */
    private String getBankBeanName(BaseMessage base) throws GopayException {
        if (StringUtils.equals(BankConstants.BANK_LOGO_ICBC, base.getBank()) && base instanceof IcbcB2cMessage) {
            return "ICBC-B2C";
        } else if (StringUtils.equals(BankConstants.BANK_LOGO_BOCOM, base.getBank()) && base instanceof BocomB2bReq) {
            return "BOCOM-B2B";
        } else if (StringUtils.equals(BankConstants.BANK_LOGO_CMBC, base.getBank()) && base instanceof CmbcB2cMessage) {
            return "CMBC-B2C";
        } else if (StringUtils.equals(BankConstants.BANK_LOGO_CMBC, base.getBank()) && base instanceof CmbcB2bMessage) {
            return "CMBC-B2B";
        } else if (StringUtils.equals(BankConstants.BANK_LOGO_BOBJ, base.getBank()) && base instanceof BobjB2cMessage) {
            return "BOBJ-B2C";
        } else if (StringUtils.equals(BankConstants.BANK_LOGO_CITIC, base.getBank()) && base instanceof CiticB2cMessage) {
            return "CITIC-B2C";
        } else if (StringUtils.equals(BankConstants.BANK_LOGO_CITIC, base.getBank()) && base instanceof CiticB2bMessage) {
            return "CITIC-B2B";
        } else if (StringUtils.equals(BankConstants.BANK_LOGO_ABC, base.getBank()) && base instanceof AbcB2cMessage) {
            return "ABC-B2C";
        } else if (StringUtils.equals(BankConstants.BANK_LOGO_ABC, base.getBank()) && base instanceof AbcB2bMessage) {
            return "ABC-B2B";
        } else if (StringUtils.equals(BankConstants.BANK_LOGO_HXBC, base.getBank()) && base instanceof HXEB2CReqPay) {
            return "HXBC-B2C";
        } else if (StringUtils.equals(BankConstants.BANK_LOGO_YSPAY, base.getBank()) && base instanceof YspayMessage) {
            return "YSPAY-B2C";
        } else if (StringUtils.equals(BankConstants.BANK_LOGO_KHPAY, base.getBank()) && base instanceof KhPayMessage) {
			return "KHPAY-B2C";
		} else if (StringUtils.equals(BankConstants.BANK_LOGO_NUCCPAY, base.getBank())
				&& StringUtils.equals(BisBankBusinessProd._01.value, base.getBankBusProd().value)
				&& StringUtils.equals(BisBankInterfaceChannel._18.value, base.getBankIntrChann().value)) {
			return "NUCCPAY-B2B";
		} else if (StringUtils.equals(BankConstants.BANK_LOGO_NUCCPAY, base.getBank())
				&& StringUtils.equals(BisBankBusinessProd._00.value, base.getBankBusProd().value)
				&& StringUtils.equals(BisBankInterfaceChannel._18.value, base.getBankIntrChann().value)) {
			return "NUCCPAY-B2C";
		} else {
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E7022);
        }
    }
    
    /**
     * @param mainOrder 
     * @param inChann 
     * @param bankBusProd
     * @return String
     * @throws GopayException
     */
    private String getOutStlmId(CpsGenMainOrder mainOrder,BisBankInterfaceChannel inChann, BisBankBusinessProd bankBusProd)throws GopayException {
        String beanSuffix = TradeType.getOrderTrandType(mainOrder.getPayChannel());
        String outStlmId = "";
        if (StringUtils.equals(TradeType.TRADE_TYPE_B2C, beanSuffix)) {
            outStlmId = InitialSpringBeanName.getOutStlmCd(inChann.value,bankBusProd.value, mainOrder.getOutStlmId());
        } else if (StringUtils.equals(TradeType.TRADE_TYPE_B2B, beanSuffix)) {
			outStlmId = InitialSpringBeanName.getOutStlmCdForNucc(inChann.value, mainOrder.getOutStlmId());
		} else {
            outStlmId = mainOrder.getOutStlmId();
        }
        return outStlmId;
    }
    
    /**
     * 是否发起退款交易
     * 
     * @param oriOutOrderId
     * @return
     */
    private boolean isSendTkOrder(String oriOutOrderId) {
        boolean flag = true;
        // 根据原交易银行订单号获取退款订单
        List<BankOrder> tkBankOrders = bankOrderService.getBankOrdersByOriBankOrderId(oriOutOrderId);
        if (tkBankOrders != null && tkBankOrders.size() > 0) {
            // 同一支付订单下多笔退款时候, 前一笔退款状态为成功或者失败的情况下, 才允许做下一笔退款
            for (int i = 0; i < tkBankOrders.size(); i++) {
                String orderStatus = tkBankOrders.get(i).getOrderStatus();
                if (BankOrderStatus.PROCESS.equals(orderStatus)) {
                    // 已存在处理中退款交易
                    logger.error("BankInteractServiceImpl refund isSendTkOrder: 已存在处理中退款交易 " + tkBankOrders.get(i).getOrderId());
                    flag = false;
                    break;
                }
            }
        }
        return flag;
    }
    
    /**
     * 是否为自动路由
     * 
     * @param merId
     * @return
     */
    private boolean isRouteOrWhiteList(String merId) {
        // 是否为白名单商户
        boolean isWhite = bisBankWhiteListMerchantsService.isWhiteListMerchant(merId);
        if (AUTO_ROUTING.equals(bisConfig.get("GOPAY.AUTO.ROUTING")) || isWhite) {
            return true;
        } else {
            return false;
        }
    }
}